<?php
/**
 * 包名：AliGenieOauth
 * 创建时间：2019.6.28
 * 创建者博客： http://blog.csdn.net/xh870189248
 * 创建者GitHub： https://github.com/xuhongv
 * 创建者：徐宏
 * 描述： 天猫精灵授权界面
 */


namespace app\api\controller\oauth;


/**
 * Class AliGenieOauth
 * @package app\api\controller\oauth
 * Tips:authorization code will expired in 30s，可以修改 OAuth2/ResponseType/AuthorizationCode.php 中
 * 的 AuthorizationCode class 的构造方法配置参数来自定义 authorization_code 有效时间。
 * client_id 是之前注册在本 Server 上的应用名称，这属于客户端管理范畴。
 */
class AliGenieOauth extends BaseController
{

    private $server;

    public function _initialize()
    {
        parent::_initialize(); // TODO: Change the autogenerated stub

        $dsn = 'mysql:dbname=' . config('database')['database'] . ';host=' . config('database')['hostname'];;
        $username = config('database')['username'];
        $password = config('database')['password'];

        \OAuth2\Autoloader::register();

        // 获取mysql数据库
        $storage = new \OAuth2\Storage\Pdo(array('dsn' => $dsn, 'username' => $username, 'password' => $password));

        // 实例化一个oauth2.0服务器
        $this->server = new \OAuth2\Server($storage);

        // Add the "Client Credentials" grant type (it is the simplest of the grant types)
        $this->server->addGrantType(new \OAuth2\GrantType\ClientCredentials($storage));

        // Add the "Authorization Code" grant type (this is where the oauth magic happens)
        $this->server->addGrantType(new \OAuth2\GrantType\AuthorizationCode($storage));

    }

    /**
     * authorize授权
     */
    public function authorize()
    {

        $request = \OAuth2\Request::createFromGlobals();
        $response = new \OAuth2\Response();

        // 校验同步请求是否有效
        if (!$this->server->validateAuthorizeRequest($request, $response)) {
            //回调给客户端
            return utilsResponse($response->getStatusCode(), 'sorry , fail!', $response->getParameters(), 200);
        }

        // 显示一个授权界面，即为要求用户输入账号密码
        if (empty($_POST)) {
            exit($this->fetch());
        }


        //登录操作
        if (request()->isPost()) {
            $getPostDataArry = input('post.');

            //从数据库查询 username
            try {
                $user = model('WcUserCode')->get(['active' => 0, 'code' => $getPostDataArry['username']]);
            } catch (\Exception $exception) {
                return utilsResponse(-1, '用户查询报错:' . $exception->getMessage(), [], 400);
            }

            //return utilsResponse(-1, '用户查询报错:' . json_encode($user), [], 400);
            if (!$user) {
                $this->error("用户不存在！");
            }

            //对比失效时间
            if (time() > $user['expire']) {
                $this->error("授权码失效，请重新获取！");
            }

            try {
                $saveUser = model('WcUserCode')->save(['active' => 1, 'code' => ''], ['user_id' => $user['user_id']]);
            } catch (\Exception $exception) {
                return utilsResponse(-1, '用户保存报错:' . $exception->getMessage(), [], 400);
            }

            if (!$saveUser) {
                $this->error("授权失败，请联系管理员！001");
            }

        } else {
            return utilsResponse(-1, 'request is not post', [], 400);
        }
        //当前的用户 id 打印下
        //utilsSaveLogs("utilsSaveLogs('***********Aligenie to me ---> ".$user['user_id'], 3);
        //同步授权使能
        $is_authorized = true;
        //最后一个参数就是当前的code和$user['id']同时入库
        $this->server->handleAuthorizeRequest($request, $response, $is_authorized, $user['user_id']);
        if ($is_authorized) {
            // this is only here so that you get to see your code in the cURL request. Otherwise, we'd redirect back to the client
            $code = substr($response->getHttpHeader('Location'), strpos($response->getHttpHeader('Location'), 'code=') + 5, 40);
        }
        $response->send();
        return '';
    }

    /**
     * 颁发token
     */
    public function token()
    {
        utilsSaveLogs("request token", 2);

        $dsn = 'mysql:dbname=' . config('database')['database'] . ';host=' . config('database')['hostname'];;
        $username = config('database')['username'];
        $password = config('database')['password'];

        \OAuth2\Autoloader::register();
        // $dsn is the Data Source Name for your database, for exmaple "mysql:dbname=my_oauth2_db;host=localhost"
        $storage = new \OAuth2\Storage\Pdo(array('dsn' => $dsn, 'username' => $username, 'password' => $password));

        // 通过校验，设置 token有效期等设置给客户端
        $this->server = new \OAuth2\Server($storage, array(
            'refresh_token_lifetime' => 2419200,
            'access_lifetime' => 172800,// 172800 / 60 / 60 = 48 小时 = 2天有效时间的 accesstoken
        ));

        // Add the "Client Credentials" grant type (it is the simplest of the grant types)
        $this->server->addGrantType(new \OAuth2\GrantType\ClientCredentials($storage));

        // Add the "Authorization Code" grant type (this is where the oauth magic happens)
        $this->server->addGrantType(new \OAuth2\GrantType\AuthorizationCode($storage));

        // Handle a request for an OAuth2.0 Access Token and send the response to the client
        $this->server->handleTokenRequest(\OAuth2\Request::createFromGlobals())->send();
    }
}